package com.base.cn.platform.os.common.mybatis;

import com.base.cn.platform.os.common.constants.CacheConstants;
import com.base.cn.platform.os.common.constants.CommonConstants;
import com.base.cn.platform.os.common.redis.RedisChannel;
import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ReflectionUtils;
import com.base.cn.platform.os.common.utils.SnowFlake;
import com.base.cn.platform.os.common.utils.StringUtils;
import net.oschina.j2cache.cache.support.util.SpringUtil;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 修改数据SQL提供类
 */
public class BaseUpdateProvider<E> extends BaseProvider{

    /**
     * 条件修改
     * @param map
     * @return
     */
    public String updateByTableNameWhereSql(Map<String,Object> map) throws IllegalAccessException {
        E entity = (E)map.get("entity");
        String whereSql = (String)map.get("whereSql");
        String tableName = (String)map.get("tableName");
        return getUpdateSql(entity,whereSql,null,tableName);
    }

    /**
     * 条件修改
     * @param map
     * @return
     */
    public String updateByWhereSql(Map<String,Object> map) throws IllegalAccessException {
        E entity = (E)map.get("entity");
        String whereSql = (String)map.get("whereSql");
        String updateSql = getUpdateSql(entity,whereSql,null);
        return updateSql;
    }

    /**
     * 单个修改数据SQL提供方法
     * @param map
     * @return
     * @throws IllegalAccessException
     */
    public String updateByIdTableName(Map<String,Object> map) throws IllegalAccessException {
        E entity = (E)map.get("entity");
        String idName = (String)map.get("idName");
        String tableName = (String)map.get("tableName");
        return this.getUpdateSql(entity,null,idName,tableName);
    }

    /**
     * 单个修改数据SQL提供方法
     * @param map
     * @return
     * @throws IllegalAccessException
     */
    public String updateById(Map<String,Object> map) throws IllegalAccessException {
        E entity = (E)map.get("entity");
        String idName = (String)map.get("idName");
        return this.getUpdateSql(entity,null,idName);
    }

    /**
     * 批量更新
     * @param map
     * @return
     * @throws IllegalAccessException
     */
    public String updateBatchSqlTableName(Map<String,Object> map) throws IllegalAccessException {
        List<E> entityList = (List<E>) map.get("list");
        if( !ObjectUtils.isEmpty(entityList)){
            Map<String,Object> result = MyBatisUtils.getEntityAllField(entityList);
            if(ObjectUtils.isEmpty(result)){
                return null;
            }
            Field[] _fields = (Field[])result.get("fields");
            String tableName = (String)map.get("tableName");
            return getUpdateBatchSql(entityList,_fields,tableName);
        }
        return null;
    }

    /**
     * 批量更新
     * @param map
     * @return
     * @throws IllegalAccessException
     */
    public String updateBatchSql(Map<String,Object> map) throws IllegalAccessException {
        List<E> entityList = (List<E>) map.get("list");
        if( !ObjectUtils.isEmpty(entityList)){
            Map<String,Object> result = MyBatisUtils.getEntityAllField(entityList);
            if(ObjectUtils.isEmpty(result)){
                return null;
            }
            E entity = (E)result.get("entity");
            String tableName = MyBatisUtils.getTableName(entity);
            Field[] _fields = (Field[])result.get("fields");
            return getUpdateBatchSql(entityList,_fields,tableName);
        }
        return null;
    }

    /**
     * 获取批量更新的SQL
     * @param entityList
     * @param _fields
     * @param tableName
     * @return
     */
    private String getUpdateBatchSql(List<E> entityList,Field[] _fields,String tableName){
        StringBuilder sql = new StringBuilder("insert into ");
        sql.append(" "+tableName +" (");
        String columnNames = "";
        String duplicateKeySql = "";
        for(Field field : _fields){
            String name = field.getName();
            if(!name.equals(CommonConstants.TENANT_ID_NAME)){
                columnNames +=name+",";
                duplicateKeySql +="`"+ name +"`=values(`"+name+"`),";
            }
        }
        columnNames = StringUtils.subHeadTailString(columnNames,",");
        sql.append(columnNames);
        sql.append(" )");
        sql.append(" values");
        int index = 0;
        String valueSql = "";
        for(E _entity: entityList){
            String values="";
            for(Field field : _fields){
                String name = field.getName();
                if(!name.equals(CommonConstants.TENANT_ID_NAME)){
                    //验证id是否存在
                    if(name.equals("id")){
                        BigDecimal id =(BigDecimal) ReflectionUtils.getFieldValue(_entity, "id");
                        if(ObjectUtils.isEmpty(id)||id.compareTo( new BigDecimal(0))==0){
                            RedisChannel redisChannel = SpringUtil.getBean(RedisChannel.class);
                            ReflectionUtils.invokeMethod(_entity,"setId",BigDecimal.class,new BigDecimal(redisChannel.getNextId(CacheConstants.ID,1L)));
                        }
                    }
                    values +="#{list["+index+"]."+name+"},";
                }
            }
            valueSql += "("+StringUtils.subHeadTailString(values,",")+"),";
            index++;
        }
        valueSql = StringUtils.subHeadTailString(valueSql,",");
        sql.append(valueSql);
        duplicateKeySql = StringUtils.subHeadTailString(duplicateKeySql,",");
        sql.append(" on duplicate key update ").append(duplicateKeySql);
        return sql.toString();
    }
    /**
     * 获取普通更新SQL语句
     * @param entity
     * @param whereSql
     * @param idName
     * @param tableName
     * @return
     * @throws IllegalAccessException
     */
    private String getUpdateSql(E entity, String whereSql, String idName,String tableName) throws IllegalAccessException{
        String time = DateUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss");
        SQL sql = new SQL();
        sql.UPDATE("`"+tableName+"`");
        Field[] fields = MyBatisUtils.getEntityAllField(entity);;
        for(Field field : fields){
            Object value = field.get(entity);
            String name = field.getName();
            if(!ObjectUtils.isEmpty(value) && !name.toLowerCase().equals("createtime")){
                sql.SET("`"+name+"`=#{entity."+name+"}");
            }else if(name.toLowerCase().equals("updatetime")){
                sql.SET("`"+name+"`='"+time+"'");
            }
        }
        if(idName==null){
            if(StringUtils.isEmpty(whereSql)){
                sql.WHERE("`"+tableName+"`.id=#{entity.id}");
            }
        }else {
            sql.WHERE("`"+tableName+"`."+idName+"=#{entity."+idName+"}");
        }
        if(!StringUtils.isEmpty(whereSql)){
            sql.WHERE(whereSql);
        }
        return sql.toString();
    }

    /**
     * 获取普通更新SQL语句
     * @param entity
     * @param whereSql
     * @param idName
     * @return
     * @throws IllegalAccessException
     */
    private String getUpdateSql(E entity, String whereSql, String idName) throws IllegalAccessException {
        String tableName = MyBatisUtils.getTableName(entity);
        return getUpdateSql(entity,whereSql,idName,tableName);
    }
}
